using System;
using System.IO;
using System.Web;
using System.Text;
using System.Xml;
using Mono.Unix;
using Gtk;
using Tomboy;
using System.Collections.Generic;

namespace Tomboy.Tomboy2Tracks {
	public class Tomboy2TracksNoteAddin : NoteAddin {

		Gtk.MenuItem item;
		string tracks_username = "";
		string tracks_password = "";
		string tracks_proto = "http";
		string tracks_host = "tracks.dp.cx";
		int tracks_port = 80;


		public override void Initialize ()
		{
			// LoadPreferences ();
			item = new Gtk.MenuItem (Catalog.GetString ("Sync to Tracks"));
			item.Activated += OnMenuItemActivated;
			item.Show ();
			AddPluginMenuItem (item);
		}

		public override void Shutdown ()
		{
			Logger.Warn("Shutting down addin");
			item.Activated -= OnMenuItemActivated;
			SavePreferences ();
		}

		public override void OnNoteOpened ()
		{
		}

		void OnMenuItemActivated (object sender, EventArgs args)
		{
			NoteManager noteManager = Manager;

			// Create the web request  
			try {
				System.Net.HttpWebRequest request = System.Net.WebRequest.Create(tracks_proto + "://" + tracks_host + ":" + tracks_port + "/todos.xml") as System.Net.HttpWebRequest;  

				// Add authentication to request  
				request.Credentials = new System.Net.NetworkCredential(tracks_username, tracks_password);  

				// Get response  
				using (System.Net.HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse)  
				{  
					StreamReader reader = new StreamReader(response.GetResponseStream());  

					XmlDocument doc = new XmlDocument();
					string xmlContents = reader.ReadToEnd();
					doc.LoadXml(xmlContents);
					XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
					ns.AddNamespace("bk", "urn:samples");

					XmlElement root = doc.DocumentElement;
					// we want to get all of the contexts, so that we can fetch the appropriate context information from the server
					XmlNodeList nodes = root.SelectNodes("//todo", ns);

					Dictionary<string, string> listOfContexts = FetchListOf("contexts");
					Dictionary<string, string> listOfProjects = FetchListOf("projects");

					// this properly returns nodes, but those nodes have no value
					foreach(XmlNode node in nodes)
					{
						bool doubleLineFeedAdded = false;
						string noteEntryTitle = node["description"].InnerText;
						string noteDueDate = node["due"].InnerText;
						string noteProjectName;
						string noteContextName;
						listOfProjects.TryGetValue(node["project-id"].InnerText, out noteProjectName);
						listOfContexts.TryGetValue(node["context-id"].InnerText, out noteContextName);
						string noteEntryContents = "<note-content>" + node["notes"].InnerText; // + "</note-content>";
						if (String.Compare(noteDueDate, "", false) == 1) {
							noteEntryContents += "\n\n";
							noteEntryContents += "\nDue: " + noteDueDate;
							doubleLineFeedAdded = true;
						}
						if (String.Compare(noteProjectName, "", false) == 1) {
							if (!doubleLineFeedAdded) { noteEntryContents += "\n\n"; doubleLineFeedAdded = true; }
							noteEntryContents += "\nProject: " + noteProjectName;
						}
						if (String.Compare(noteContextName, "", false) == 1) {
							if (!doubleLineFeedAdded) { noteEntryContents += "\n\n"; doubleLineFeedAdded = true; }
							noteEntryContents += "\nContext: " + noteContextName;
						}
						noteEntryContents += "</note-content>";
						Note localNote = noteManager.Find(Catalog.GetString(noteEntryTitle));

						if (localNote == null) {
							Logger.Log("Note " + noteEntryTitle + " doesn't exist.  Creating.");
							Note tracksNote = noteManager.Create (Catalog.GetString(noteEntryTitle), noteEntryContents);
							tracksNote.QueueSave(ChangeType.ContentChanged);
						} else {
							Logger.Log("Note " + noteEntryTitle + " exists.");
						}
					}
				}
			} catch (System.Net.WebException e) {
				Logger.Warn ("Error fetching REST feed: {0}", e);
				System.Environment.Exit(0);
			}

		}

		protected void SavePreferences ()
		{
			try {
				Preferences.Set ("/apps/tomboy/tracks/username", tracks_username);
				Preferences.Set ("/apps/tomboy/tracks/password", tracks_password);
				Preferences.Set ("/apps/tomboy/tracks/proto", tracks_proto);
				Preferences.Set ("/apps/tomboy/tracks/host", tracks_host);
				Preferences.Set ("/apps/tomboy/tracks/port", tracks_port);
			} catch (Exception e) {
				Logger.Warn("Error saving prefs: {0}", e);
				System.Environment.Exit(0);
			}
		}

		protected void LoadPreferences ()
		{
			try {
				tracks_username = (string) Preferences.Get ("/apps/tomboy/tracks/username");
				tracks_password = (string) Preferences.Get ("/apps/tomboy/tracks/password");
				tracks_proto = (string) Preferences.Get ("/apps/tomboy/tracks/proto");
				tracks_host = (string) Preferences.Get ("/apps/tomboy/tracks/host");
				tracks_port = (int) Preferences.Get ("/apps/tomboy/tracks/port");
			} catch (Exception e) {
				Logger.Warn ("Error loading preferences: {0}\n{1}",
						e.Message, e.StackTrace);
			}
		}

		protected Dictionary<string, string> FetchListOf(string stuff) {

			Dictionary<string, string> listOfData = new Dictionary<string, string>();

			try {
				System.Net.HttpWebRequest request = System.Net.WebRequest.Create(tracks_proto + "://" + tracks_host + ":" + tracks_port + "/" + stuff + ".xml") as System.Net.HttpWebRequest;  
				char[] charsToTrim = {'s'};
				stuff = stuff.TrimEnd(charsToTrim);

				// Add authentication to request  
				request.Credentials = new System.Net.NetworkCredential(tracks_username, tracks_password);  

				// Get response  
				using (System.Net.HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse)  
				{  
					StreamReader reader = new StreamReader(response.GetResponseStream());  

					XmlDocument doc = new XmlDocument();
					string xmlContents = reader.ReadToEnd();
					doc.LoadXml(xmlContents);
					XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
					ns.AddNamespace("bk", "urn:samples");

					XmlElement root = doc.DocumentElement;
					// we want to get all of the contexts, so that we can fetch the appropriate context information from the server
					XmlNodeList nodes = root.SelectNodes("//" + stuff, ns);

					// this properly returns nodes, but those nodes have no value
					foreach(XmlNode node in nodes)
					{
						string id = node["id"].InnerText;
						string name = node["name"].InnerText;
						listOfData.Add(id, name);
					}
				}
			} catch (System.Net.WebException e) {
				Logger.Warn ("Error fetching REST feed: {0}", e);
				System.Environment.Exit(0);
			}

			return listOfData;
		}
	}

	public class TracksSyncPreferences : Gtk.VBox
	{
		Gtk.Button open_template_button;

		public TracksSyncPreferences ()
			: base (false, 12)
		{
			Gtk.Label label = new Gtk.Label (
					Catalog.GetString (
						"Change the <span weight=\"bold\">Today: Template</span> " +
						"note to customize the text that new Today notes have."));
			label.UseMarkup = true;
			label.Wrap = true;
			label.Show ();
			PackStart (label, true, true, 0);

			open_template_button = new Gtk.Button (
					Catalog.GetString ("_Open Today: Template"));
			open_template_button.UseUnderline = true;
			open_template_button.Show ();
			PackStart (open_template_button, false, false, 0);

			ShowAll ();
		}
	}
}
